package ua.edu.nuos.tees.jdmmon.vo.implementations;

import ua.edu.nuos.tees.jdmmon.vo.interfaces.InputPackage;

import java.io.IOException;
import java.util.Arrays;

/**
 * Implementation of rtu input package
 *
 * @author Timur Yarosh
 *         22.02.13
 */
public class RtuInputPackage implements InputPackage {
    private static final int BYTE_SIZE = 8;
    private static final int INDEX_OF_DEVICE_ADDRESS = 0;
    private static final int INDEX_OF_MODBUS_FUNCTION = 1;
    private static final int INDEX_OF_DATA_SIZE = 2;
    private static final int INDEX_OF_RESPONSE_DATA = 3;
    private final int INDEX_OF_CRC;
    private final int deviceAddress;
    private final int modbusFunction;
    private final int dataSize;
    private final byte[] responseData;
    private final int crc;

    /**
     * Initialize INDEX_OF_CRC, deviceAddress, modbusFunction, dataSize, responseData and crc
     * @param rtuPackage rtu package
     */
    public RtuInputPackage(byte[] rtuPackage) throws IOException {
        INDEX_OF_CRC = rtuPackage.length - 2; // two last bytes are the CRC
        deviceAddress = rtuPackage[INDEX_OF_DEVICE_ADDRESS];
        modbusFunction = rtuPackage[INDEX_OF_MODBUS_FUNCTION];
        dataSize = rtuPackage[INDEX_OF_DATA_SIZE];
        responseData = getResponseData(rtuPackage);
        crc = getCRC(rtuPackage);
    }
    @Override
    public int getDeviceAddress() {
        return deviceAddress;
    }

    @Override
    public int getModbusFunction() {
        return modbusFunction;
    }

    @Override
    public int getDataSize() {
        return dataSize;
    }

    @Override
    public byte[] getResponseData() {
        return responseData;
    }

    @Override
    public int getCRC() {
        return crc;
    }

    /**
     * Get response data from rtu package
     *
     * @param rtuPackage rtu package
     * @return response data
     */
    private byte[] getResponseData(byte[] rtuPackage) {
        return Arrays.copyOfRange(rtuPackage, INDEX_OF_RESPONSE_DATA, INDEX_OF_CRC);
    }

    /**
     * Get response data from rtu package
     * @param rtuPackage rtu package
     * @return response data
     */
    private int getCRC(byte[] rtuPackage) {
        byte[] crc = Arrays.copyOfRange(rtuPackage, INDEX_OF_CRC, rtuPackage.length);
        return bytesArrayToNumber(crc);
    }

    /**
     * Concatenate bytes array to integer number
     * @param bytesArray bytes array
     * @return integer number
     */
    private int bytesArrayToNumber(byte[] bytesArray) {
        int buffer = 0;
        for (byte aBytesArray : bytesArray) {
            buffer = (buffer << BYTE_SIZE) | (aBytesArray < 0 ? aBytesArray + 256 : aBytesArray);
        }
        return buffer;
    }
}
